const fs = require("node:fs/promises"), querystring = require('querystring'), path = require('path');
const pan = require("./pan"), https = require("node:https");

/** 百度盘操作类 */
class Baidu {
    /** 基本信息缓存文件名 */
    cfg = "user";
    /** 登录后的基本信息 */
    user = null;
    /** 重新登录回调函数 */
    cb_reload = null;

    /** 构造函数 */
    constructor(cfg = "user", cb_reload = null){
        this.cfg = cfg;
        this.cb_reload = cb_reload;
        this.loginCheck();
    }
    /** 检测登录状态 */
    async loginCheck(){
        if(this.user?.access_token) return true;

        try{
            await fs.stat("./" + this.cfg + ".json");
            let userstr = await fs.readFile("./" + this.cfg + ".json");
            this.user = JSON.parse(userstr);
            if(this.user.access_token) return true;
            return false;
        }catch(e){
            console.log(e);
            return false;
        }
    }
    /** 获取登录地址 */
    loginUrl(){
        return "https://openapi.baidu.com/oauth/2.0/authorize?response_type=token&client_id=" + pan.client_id + "&redirect_uri=oob&scope=basic,netdisk&login_type=sms"
    }
    /** 登录成功 */
    async loginSuccess(url){
        console.log("loginSuccess Url", url);
        if(url.indexOf("success") != -1){
            let query = querystring.parse(url.substr(url.indexOf("#")+1));
            await fs.writeFile("./" + this.cfg + ".json", JSON.stringify(query));
            //delete require.cache[__dirname + path.sep + this.cfg + ".json"];
            //this.user = require("./" + this.cfg + ".json");
            let userstr = await fs.readFile("./" + this.cfg + ".json");
            this.user = JSON.parse(userstr);
            return true;
        }
        return false;
    }

    BaseOptions = {
        hostname: 'pan.baidu.com',
        port: 443,
        path: '/',
        method: 'GET',
        headers: {
            'User-Agent': 'pan.baidu.com'
        }
    };
    /** 检查http请求错误信息 */
    async get(url, opt){
        let opts = Object.assign({}, this.BaseOptions);
        if(opt) opts = Object.assign(opts, opt);
        opts.path = url;
        return new Promise((resolve, reject)=>{
            let req = https.request(opts, (res)=>{
                let ret = Buffer.allocUnsafe(0)
                res.on('data', (chunk)=>{
                    ret = Buffer.concat([ret, chunk], ret.length + chunk.length);
                });
                res.on('end', async ()=>{
                    let jobj = ret.toString();
                    if(res.headers["content-type"].indexOf("json") != -1){
                        jobj = JSON.parse(jobj);
                    }
                    if(jobj.errno){
                        console.log("res", ret.toString());
                        if(jobj.errno == -6){
                            await fs.writeFile("./" + this.cfg + ".json", '{}');
                            this.cb_reload && this.cb_reload();
                        }
                    }
                    resolve(jobj)
                });
            });
            req.end();        
        })
    }
    /** 获取用户信息 */
    async info(){
        if(!this.user) await this.loginCheck();
        return await this.get("/rest/2.0/xpan/nas?method=uinfo&access_token=" + this.user.access_token);
    }
    /** 获取用户信息 */
    async quota(){
        if(!this.user) await this.loginCheck();
        return await this.get("/api/quota?access_token=" + this.user.access_token);
    }
    /** 当前目录文件列表 */
    async list(path){
        if(!this.user) await this.loginCheck();
        return await this.get("/rest/2.0/xpan/file?method=list&dir=" + encodeURI(path||'/') + "&access_token=" + this.user.access_token);
    }
    /** 获取视频文件 */
    async video(path, adToken){
        if(!this.user) await this.loginCheck();
        let opt = Object.assign({}, this.BaseOptions);
        opt.headers["User-Agent"] = "xpanvideo;netdisk;1.0.0;win10;22H2;ts";
        let url = `/rest/2.0/xpan/file?method=streaming&path=${encodeURI(path)}&type=M3U8_AUTO_720&access_token=${this.user.access_token}`;
        if(adToken){
            url += `&adToken=${encodeURIComponent(adToken)}`;
        }
        //console.log(url);
        let text = await this.get(url, opt);
        if(typeof text == 'string'){
            //console.log(text);
            return Buffer.from(text).toString("base64");
        }else{
            return text;
        }
    }
}

module.exports = Baidu;